package com.moon.java.code.analyzer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.alibaba.fastjson2.JSON;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;

/**
 * 获取一个项目的所有类和其中的方法名和字段名
 * 
 * @Description:
 * @author wangzhiyue
 * @date 2025/03/14 11:06:38
 */
public class JavaFileTraversal {

    // 序列化方法，将 Map 保存到文件
    public static void serializeMap(Map<String, MethodFieldInfo> map, String filePath) throws IOException {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath))) {
            oos.writeObject(map);
        }
    }

    // 反序列化方法，从文件中读取 Map
    @SuppressWarnings("unchecked")
    public static Map<String, MethodFieldInfo> deserializeMap(String filePath) throws IOException, ClassNotFoundException {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {
            return (Map<String, MethodFieldInfo>) ois.readObject();
        }
    }

    public static Map<String, MethodFieldInfo> fileTraversalMap(String path, boolean cache) {
        Map<String, MethodFieldInfo> result = new HashMap<String, MethodFieldInfo>();
        try {
            Path projectPath = Paths.get(path);
            String fileCachePath = projectPath.getFileName() + ".ser";
            if (cache) {
                File serializedFile = new File(fileCachePath);
                if (serializedFile.exists()) {
                    result = deserializeMap(fileCachePath);
                    return result;
                }
            }
            JavaFileVisitor visitor = new JavaFileVisitor();
            Files.walkFileTree(projectPath, visitor);
            result = visitor.getFileInfoMap();
            serializeMap(result, fileCachePath);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void main(String[] args) {
        Map<String, MethodFieldInfo> deserializedMap = fileTraversalMap("D:\\git\\ecej-pay-transaction\\transaction-core", true);
        System.out.println("Map: " + JSON.toJSONString(deserializedMap));
    }

    // 定义一个包含方法名和字段名集合的类
    public static class MethodFieldInfo implements Serializable {
        private static final long serialVersionUID = 1L;
        Set<String> methodNames = new HashSet<String>();
        Set<String> fieldNames = new HashSet<String>();

        public Set<String> getMethodNames() {
            return methodNames;
        }

        public void setMethodNames(Set<String> methodNames) {
            this.methodNames = methodNames;
        }

        public Set<String> getFieldNames() {
            return fieldNames;
        }

        public void setFieldNames(Set<String> fieldNames) {
            this.fieldNames = fieldNames;
        }

    }

    // 定义一个文件访问器类，用于遍历 Java 文件
    public static class JavaFileVisitor extends SimpleFileVisitor<Path> {
        private Map<String, MethodFieldInfo> fileInfoMap = new HashMap<>();

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            if (file.toString().endsWith(".java")) {
                String fileName = removeFileExtension(file.getFileName().toString());
                MethodFieldInfo info = analyzeJavaFile(file);
                fileInfoMap.put(fileName, info);
            }
            return FileVisitResult.CONTINUE;
        }

        // 移除文件扩展名
        private String removeFileExtension(String fileName) {
            int lastIndex = fileName.lastIndexOf('.');
            if (lastIndex != -1) {
                return fileName.substring(0, lastIndex);
            }
            return fileName;
        }

        // 分析 Java 文件，收集方法名和字段名
        private MethodFieldInfo analyzeJavaFile(Path file) throws IOException {
            CompilationUnit cu = StaticJavaParser.parse(file);
            MethodFieldInfo info = new MethodFieldInfo();

            // 收集方法名
            cu.findAll(MethodDeclaration.class).forEach(method -> {
                info.methodNames.add(method.getNameAsString());
            });

            // 收集字段名
            cu.findAll(FieldDeclaration.class).forEach(field -> {
                field.getVariables().forEach(variable -> {
                    info.fieldNames.add(variable.getNameAsString());
                });
            });

            return info;

        }

        public Map<String, MethodFieldInfo> getFileInfoMap() {
            return fileInfoMap;
        }
    }
}